<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Online Svg Editor</title>
  <style type="text/css">
    body{
      padding: 0;
      margin: 0;
      color: #464c5b;
      font-size: 14px;
      line-height: 1.4;
      font-family: Helvetica Neue,Helvetica,PingFang SC,Hiragino Sans GB,Microsoft YaHei,\\5FAE\8F6F\96C5\9ED1,Arial,sans-serif;
    }
    .view,
    .editor{
      width: 100%;
      display: block;
      box-sizing: border-box;
    }
    .view{
      height: 80vh;
      padding: 15px;
    }
    .editor{
      height: 20vh;
      padding: 15px;
      line-height: 1.4;
      outline: none;
      color: rgba(255,255,255, 0.7);
      background: #282C34;
      border: solid 1px #2C333D;
      font-family: inherit;
      font-size: 2rem;
    }
    .editor:focus {
      border: solid 1px #1883D7;
    }
    .icon-svg{
      max-width: 600px;
      max-height: 600px;
      margin: 0 auto;
      margin-top: 50px;
      display: block;
      background: #F2F5FA;
    }
    .icon-svg path{
      transition: all 0.5s ease;
    }
  </style>
</head>
<body>
<div id="app">
<div class="view">
  <svg
    xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink"
    class="icon-svg"

    viewBox="0 0 40 40"
    >
    <path :d="path" stroke-linecap="round" stroke-width="0.3" stroke="#282C34" fill="none"></path>
  </svg>
</div>
<textarea ref="editor" class="editor" v-model="path"></textarea>
</div>
<script src="https://cdn.bootcss.com/vue/2.5.17-beta.0/vue.min.js"></script>
<script type="text/javascript">
  window.addEventListener('load', () => {
    function doGetCaretPosition (input) {
      var iCaretPos = 0;
      // IE Support
      if (document.selection) {
        // Set focus on the element
        input.focus()
        // To get cursor position, get empty selection range
        var oSel = document.selection.createRange()
        // Move selection start to 0 position
        oSel.moveStart('character', -input.value.length)
        // The caret position is selection length
        iCaretPos = oSel.text.length
      } else if (input.selectionStart || input.selectionStart === '0') {
        // Firefox support
        iCaretPos = input.selectionStart
      }
      return iCaretPos
    }
    window.app = new Vue({
      el: '#app',
      data: {
        path: 'M5,20 A16,16,0,0,1,35,20',
        editor: null,
        selectionStart: 0,
        selectionEnd: 0,
        selectionText: '',
        carePosition: 0
      },
      mounted () {

        this.editor = this.$refs['editor']
        let that = this
        function setSelect (direction) {
          if (window.getSelection().toString().length > 0) {
            return false
          }
          let position = doGetCaretPosition(that.editor)
          if (direction === 'right') {
            if (position > 0 && !isNaN(Number(that.path[position]))) {
              that.editor.setSelectionRange(position, position + 1)
            }
          } else {
            if (position > 0 && !isNaN(Number(that.path[position - 1]))) {
              that.editor.setSelectionRange(position - 1, position)
            }
          }
        }

        this.editor.addEventListener('click', e => {
          // console.log('click')
          setSelect()
        })
        this.editor.addEventListener('focus', e => {
          // console.log('focus', e)
          this.selectionText = ''
        })
        this.editor.addEventListener('select', e => {
          // console.log('select', e)
          this.selectionText = window.getSelection().toString()
          let {selectionStart, selectionEnd} = this.editor
          this.selectionStart = selectionStart
          this.selectionEnd = selectionEnd
          // 防止触发click
          e.preventDefault()
        })
        this.editor.addEventListener('mousewheel', (e) => {
          // console.log('mousewheel')
          this.carePosition = doGetCaretPosition(this.editor)
          // console.log(this.selectionText, this.carePosition)

          // 如果选中内容不等于空，并且是数字
          if (this.selectionText.length > 0 && !isNaN(Number(this.selectionText))) {
            let val = 0
            // up
            if (e.wheelDelta > 0) {
              val = +this.selectionText + 1
            } else {
              val = +this.selectionText - 1
            }
            // 设置选中内容，并不会触发change事件
            this.editor.setRangeText(val)
            this.selectionText = val + ''
          }
          this.path = this.editor.value
        })

        document.addEventListener('keydown', e => {
          // console.log(e.which)
          // 方向键，上下左右38, 40, 37, 39
          if ([38, 40].indexOf(e.which) > -1) {
            if (this.selectionText.length > 0 && !isNaN(Number(this.selectionText))) {
              let val = 0
              if (e.which === 38) {
                val = +this.selectionText + 1
              } else {
                val = +this.selectionText - 1
              }
              this.editor.setRangeText(val)
              this.selectionText = val + ''
              this.path = this.editor.value
            }
            e.preventDefault()
          }
        })
        document.addEventListener('keyup', e => {
          if (e.which === 37) {
            setSelect()
          }
          if (e.which === 39) {
            setSelect('right')
          }
        })
      }
    })
  })
</script>
</body>
</html>